<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>文件上传</title>
    <script type="text/javascript" src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>
    <style>
        * {
            margin: 0px;
            padding: 0px;
            border: none;
            outline: none;
        }

        body {
            overflow: hidden;
            background-color: rgb(236, 236, 236);
        }

        .wrapper {
            margin: 15% auto;
            display: flex;
            align-items: center;
            flex-flow: column;
            height: 100px;
        }


        .uploadForm {
            height: 100%;
            display: flex;
            flex-flow: column;
            justify-content: space-evenly;
        }

        .buttonWrapper {
            width: 100%;
            display: flex;
            justify-content: flex-end;
        }

        .selectFileButton, .uploadFileButton, .pauseFileButton, .cancelFileButton {
            width: 85px;
            height: 35px;
            font-size: 13px;
            border-radius: 5px;
            margin-right: 10px;
            font-weight: bold;
            font-family: "华文宋体", serif;
        }

        .selectFileButton {
            background-color: rgb(255, 119, 1);
        }

        .uploadFileButton {
            background-color: rgb(255, 223, 5);
        }

        .pauseFileButton {
            background-color: rgb(214, 90, 255);
        }

        .cancelFileButton {
            background-color: rgb(126, 125, 201);
        }

        .realSelectFileInput {
            display: none;
        }

        .pauseFileButton {
            margin-right: 0px;
        }

        .filenameTip {
            position: absolute;
            display: none;
            font-size: 12px;
            border-radius: 2px;
            background-color: rgba(216, 234, 92, .9);
            padding: 0 5px;
            color: black;
        }

        .selectFileButton:hover, .uploadFileButton:hover, .pauseFileButton:hover, .cancelFileButton:hover {
            cursor: pointer;
        }

        .outer {
            width: 400px;
            height: 30px;
            border-radius: 10px;
            border: 2px solid rgb(50, 148, 248);
            overflow: hidden;
        }

        .inner {
            height: 100%;
            text-align: center;
            line-height: 30px;
            background-color: #96ef16;
            transition: 0.1s width;
            width: 0;
            color: #0000ff;
        }

        .message {
            position: fixed;
            font-size: 18px;
            left: 50%;
            transform: translateX(-50%);
            top: 5%;
            display: none;
        }

        .recordFileId {
            display: none;
        }

        .not-allowed-click:hover {
            cursor: not-allowed;
        }

    </style>
</head>
<body>
<div class="wrapper">
    <form class="uploadForm">
        <div class="outer">
            <div class="inner"></div>
        </div>
        <div class="buttonWrapper">
            <button class="selectFileButton" type="button">选择文件</button>
            <button class="uploadFileButton" type="button">上传</button>
            <button class="cancelFileButton not-allowed-click" type="button" disabled>取消</button>
            <button class="pauseFileButton not-allowed-click" type="button" clickCount="1" disabled>暂停</button>
            <input class="realSelectFileInput" type="file" name="file"/>
            <input class="recordFileId" value="" type="text" name="id"/>
        </div>
    </form>
    <div class="filenameTip">当前未选择任何文件</div>
</div>
<div class="message">失败失败失败失败</div>
<script>
    let selectFileButton = $(".selectFileButton");
    let realSelectFileInput = $(".realSelectFileInput");
    let uploadFileButton = $(".uploadFileButton");
    let filenameTip = $(".filenameTip");
    let inner = $(".inner");
    let message = $(".message");
    let pauseFileButton = $(".pauseFileButton");
    let recordFileId = $(".recordFileId");
    let cancelFileButton = $(".cancelFileButton");
    let interval;
    let isSuccess = true;
    let isCancel = false;
    let isPause = false;

    //显示提示信息
    function showMessage(result) {
        if (!result.message) {
            return;
        }
        let color = result.flag ? "green" : "red";
        message.css("color", color);
        message.text(result.message);
        message.fadeIn(1000);
        message.fadeOut(1000);
        console.log(result)
    }

    //禁止按钮点击
    function prohibitClick() {
        pauseFileButton.attr("disabled", true);
        cancelFileButton.attr("disabled", true);
        cancelFileButton.addClass("not-allowed-click");
        pauseFileButton.addClass("not-allowed-click");
    }

    //允许按钮点击
    function allowClick() {
        pauseFileButton.attr("disabled", false);
        cancelFileButton.attr("disabled", false);
        pauseFileButton.removeClass("not-allowed-click");
        cancelFileButton.removeClass("not-allowed-click");
    }

    //重置状态
    function resetState(result) {
        showMessage(result);
        clearInterval(interval);
        selectFileButton.text("选择文件");
        realSelectFileInput.val("");
        filenameTip.text("再次选择文件");
        recordFileId.val("");
        pauseFileButton.attr("clickCount", "1");
        pauseFileButton.attr("disabled",true);
        cancelFileButton.attr("disabled",true);
        prohibitClick();
    }

    //继续分片上传文件 file--文件类 index--上传下标 uploadId--文件id
    function postUploadFile(file, offset, index, uploadId) {
        let size = file.size;//总大小
        let shardSize = 1024 * 1024;//每个分片的大小(1024 * 1024 == 1Mb)
        let shardCount = Math.ceil((size - offset) / shardSize);//总片数
        let start = index * shardSize + offset;//开始切片位置
        let end = start + shardSize;//结束位置
        //最后一次的分片大小
        if (shardCount === index + 1) {
            end = size;
        }
        let packet = file.slice(start, end);//将文件进行切片
        //构建form表单进行提交
        let form = new FormData();
        form.append("data", packet);//数据
        form.append("totalSize", size);//总大小
        form.append("uploadId", uploadId);//文件id
        form.append("shardCount", shardCount + "");//总分片数量
        form.append("count", index + 1);//当前为第几片
        form.append("start", start + "");//当前为第几片
        form.append("end", end + "");//当前为第几片
        form.append("currentSize", (end - start) + "");//当前传输的大小
        let f = new File([packet], "");
        form.append("file", f);
        console.log("第" + (index + 1) + "次上传：" + JSON.stringify(form));
        //文件上传
        $.ajax({
            url: '/upload/uploadFile',//请求url
            type: 'POST',//请求方式
            cache: false, //不必须
            data: form,//数据
            processData: false,//必须 告诉jquery不要对form进行处理
            contentType: false,//必须 指定为false才能形成正确的Content
            success: function (result) {
                showMessage(result);
                isSuccess = result.flag;
                //失败
                if (!result.flag) {
                    prohibitClick();
                }
                //成功且文件未上传完毕
                if ((!isPause) && (!isCancel) && result.flag && (index + 1) < shardCount) {
                    console.log("第" + (index + 1) + "次上传完毕：");
                    postUploadFile(file, offset, index + 1, uploadId);
                }
            },
            error: function () {
                showMessage({flag: false, message: "上传失败！"})
                prohibitClick();
                isSuccess = false;
            }
        })
    }


    //页面加载完毕
    $(function () {
        //模拟选择文件
        selectFileButton.click(function () {
            realSelectFileInput.click();
        });
        //监听文件变化
        realSelectFileInput.change(function () {
            let filePath = $(this).val();
            let arr = filePath.split('\\');
            let fileName = arr[arr.length - 1];
            selectFileButton.text("已选择文件");
            filenameTip.text("已选择文件：" + fileName);
        });
        //弹出提示
        selectFileButton.mousemove(function (event) {
            let left = event.pageX + 5;
            let top = event.pageY + 5;
            filenameTip.css("left", left + "px");
            filenameTip.css("top", top + "px");
            filenameTip.css("display", "block");
        });
        //隐藏提示
        selectFileButton.mouseleave(function () {
            filenameTip.css("display", "none");
        });
        //上传文件
        uploadFileButton.click(function () {
            //初始化状态
            allowClick();
            isCancel = false;
            //获取文件
            console.log(realSelectFileInput.prop("files"))
            let file = realSelectFileInput.prop("files")[0];
            if (!file) {
                showMessage({flag: false, message: "上传失败！未选择文件！"});
                return;
            }
            let name = file.name;
            //获取文件id
            $.ajax({
                url: '/upload/getUploadId',
                type: 'GET',
                cache: false, //不必须
                data: {filename: name},
                async: false,//同步
                success: function (result) {
                    //设置id参数
                    recordFileId.val(result.data.id);
                    //定时获取进度
                    interval = setInterval(function () {
                        //获取进度
                        $.ajax({
                            url: "/upload/getPercent",
                            type: 'GET',
                            data: {id: recordFileId.val()},
                            success: function (result) {
                                let newWidth = result.data + "%";
                                inner.css("width", newWidth);
                                inner.text(newWidth);
                                if (result.data >= 100) {
                                    let r = {flag: true, message: "上传成功！"};
                                    resetState(r)
                                }
                                if (!isSuccess) {
                                    clearInterval(interval);
                                    inner.css("width", "0%");
                                    inner.text("0%");
                                }
                            },
                            error: function () {
                                clearInterval(interval);
                                showMessage({flag: false, message: "请求错误!请重试！"});
                            }
                        })

                    }, 500);
                    //分片上传文件
                    postUploadFile(file, 0, 0, result.data.id);
                },
                error: function () {
                    showMessage({flag: false, message: "获取id失败！"})
                    isSuccess = false;
                }
            })
        });
        //暂停上传
        pauseFileButton.click(function () {
            pauseFileButton.attr("disabled", true);
            pauseFileButton.addClass("not-allowed-click");
            let clickCount = parseInt(pauseFileButton.attr("clickCount"));
            pauseFileButton.attr("clickCount", clickCount + 1);
            if (clickCount % 2) {
                $.ajax({
                    url: '/upload/pauseUpload',
                    type: 'GET',
                    data: {id: recordFileId.val()},
                    success: function (result) {
                        showMessage(result);
                        pauseFileButton.attr("disabled", false);
                        pauseFileButton.text("继续");
                        pauseFileButton.removeClass("not-allowed-click");
                        isPause = true;
                    },
                    error: function () {
                        showMessage({flag: false, message: "请求失败！"});
                    }
                })
            } else {
                //获取文件
                let file = realSelectFileInput.prop("files")[0];
                $.ajax({
                    url: '/upload/continueUpload',
                    type: 'GET',
                    data: {id: recordFileId.val()},
                    success: function (result) {
                        showMessage(result);
                        pauseFileButton.attr("disabled", false);
                        pauseFileButton.removeClass("not-allowed-click");
                        pauseFileButton.text("暂停");
                        isPause = false;
                        //分片上传文件
                        postUploadFile(file, result.data, 0, recordFileId.val());
                    },
                    error: function () {
                        showMessage({flag: false, message: "请求失败！"});
                    }
                })
            }
        });
        //取消上传
        cancelFileButton.click(function () {
            $.ajax({
                url: '/upload/cancelUpload',
                type: 'GET',
                data: {id: recordFileId.val()},
                success: function (result) {
                    isCancel = true;
                    resetState(result);
                },
                error: function () {
                    showMessage({flag: false, message: "请求失败！"});
                }
            })

        })
    })
</script>
</body>
</html>